package com.easygoods.service;

import com.bestvike.stone.core.lang.RandomUtils;
import com.bestvike.stone.core.lang.StringUtils;
import com.bestvike.stone.core.time.DateUtils;
import com.bestvike.stone.spring.exception.BusinessException;
import com.bestvike.stone.spring.exception.ErrorCode;
import com.bestvike.stone.spring.service.BaseService;
import com.easygoods.dao.MemberExternalDao;
import com.easygoods.dao.MemberInfoDao;
import com.easygoods.dao.StoreInfoDao;
import com.easygoods.entity.MemberExternal;
import com.easygoods.entity.MemberInfo;
import com.easygoods.entity.StoreInfo;
import com.easygoods.enums.AvatarType;
import com.easygoods.enums.Channel;
import com.easygoods.enums.UserState;
import com.easygoods.request.ExternalRegisterRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;

/**
 * Created by 许崇雷 on 2018-12-25.
 */
@Service
public class AuthService extends BaseService {
    public static final String ROOT_MEMBER_ID = "root";
    private static WeChatService weChatServiceStatic;
    @Autowired
    private MemberInfoDao memberInfoDao;
    @Autowired
    private MemberExternalDao memberExternalDao;
    @Autowired
    private SmsService smsService;
    @Autowired
    private StoreInfoDao storeInfoDao;
    @Autowired
    private PointService pointService;
    @Autowired
    private ConfigService configService;
    @Autowired
    private WeChatService weChatService;

    //判断指定渠道下是否有 openId
    public static boolean hasOpenId(Channel channel, String openId) {
        if (channel == null)
            return false;
        switch (channel) {
            case WeChat:
                return weChatServiceStatic.hasOpenId(openId);
            case AliPay:
                return false;
            default:
                return false;
        }
    }

    @PostConstruct
    private void init() {
        weChatServiceStatic = this.weChatService;
    }

    //注册
    @Transactional
    public void externalRegister(ExternalRegisterRequest request) {
        //验证验证码
        this.smsService.checkRegisterSms(request);
        //验证 openid
        Example externalExample = new Example(MemberExternal.class);
        externalExample.createCriteria().andEqualTo(MemberExternal.EXTERNAL_CHANNEL, request.getChannel())
                .andEqualTo(MemberExternal.EXTERNAL_ID, request.getOpenId());
        int countByOpenId = this.memberExternalDao.selectCountByExample(externalExample);
        if (countByOpenId > 0)
            throw new BusinessException(ErrorCode.ERROR_SERVER, "该账号已注册,请直接登录");

        //验证上级
        if (StringUtils.isEmpty(request.getRefMemberId()))
            request.setRefMemberId(ROOT_MEMBER_ID);

        //查询上级
        final MemberInfo refMemberInfo = this.memberInfoDao.selectByPrimaryKey(request.getRefMemberId());
        if (refMemberInfo == null)
            throw new BusinessException(ErrorCode.ERROR_SERVER, "无效的推荐人");

        //用户主体是否存在,不存在则创建
        Example exampleByMobile = new Example(MemberInfo.class);
        exampleByMobile.createCriteria().andEqualTo(MemberInfo.MOBILE, request.getMobile());
        MemberInfo memberInfo = this.memberInfoDao.selectOneByExample(exampleByMobile);
        if (memberInfo == null) {
            //会员表
            memberInfo = new MemberInfo();
            memberInfo.setId(RandomUtils.randomUUID());
            memberInfo.setGrade(0);
            memberInfo.setMobile(request.getMobile());
            memberInfo.setEmail(null);
            memberInfo.setNickName(request.getNickName());
            memberInfo.setPwd(null);
            memberInfo.setPwdSalt(RandomUtils.randomUUID());
            memberInfo.setRefMemberId(request.getRefMemberId());
            memberInfo.setAvatarType(AvatarType.Url.name());
            memberInfo.setAvatar(request.getAvatarUrl());
            memberInfo.setRegisterTime(DateUtils.now());
            memberInfo.setState(UserState.Normal.name());
            memberInfo.setDefaultReceiveAddress(null);
            memberInfo.setDefaultSendAddress(null);
            memberInfo.setTotalInviteCoupon(BigDecimal.ZERO);
            memberInfo.setTotalEarnCash(BigDecimal.ZERO);
            memberInfo.setTotalInviteFirstCash(BigDecimal.ZERO);
            memberInfo.setTotalInviteManyCash(BigDecimal.ZERO);
            memberInfo.setTotalTeamCash(BigDecimal.ZERO);
            memberInfo.setRemainCash(BigDecimal.ZERO);
            memberInfo.setTotalPoint(0);
            memberInfo.beforeInsert();
            final int memberInsert = this.memberInfoDao.insert(memberInfo);
            if (memberInsert != 1) {
                this.log.warn("创建用户失败 mobile:" + memberInfo.getMobile());
                throw new BusinessException(ErrorCode.ERROR_SERVER, "注册失败");
            }

            //会员-店铺
            StoreInfo storeInfo = new StoreInfo();
            storeInfo.setId(RandomUtils.randomUUID());
            storeInfo.setMemberId(memberInfo.getId());
            storeInfo.setBuyNum(0);
            storeInfo.setBuyOriginAmt(BigDecimal.ZERO);
            storeInfo.setBuyMemberAmt(BigDecimal.ZERO);
            storeInfo.setBuyPayAmt(BigDecimal.ZERO);
            storeInfo.beforeInsert();
            final int insertStore = this.storeInfoDao.insert(storeInfo);
            if (insertStore != 1) {
                this.log.warn("创建用户商店失败 mobile:" + memberInfo.getMobile());
                throw new BusinessException(ErrorCode.ERROR_SERVER, "注册失败");
            }
        }

        //会员-外部
        MemberExternal memberExternal = new MemberExternal();
        memberExternal.setId(RandomUtils.randomUUID());
        memberExternal.setExternalChannel(request.getChannel().name());
        memberExternal.setExternalId(request.getOpenId());
        memberExternal.setMemberId(memberInfo.getId());
        memberExternal.beforeInsert();
        final int externalCount = this.memberExternalDao.insert(memberExternal);
        if (externalCount != 1) {
            this.log.warn("创建外部用户失败 mobile:" + memberInfo.getMobile());
            throw new BusinessException(ErrorCode.ERROR_SERVER, "注册失败");
        }

        //注册赠送积分
        this.pointService.increasePoint(memberInfo.getId(), this.configService.getRegisterPoint(), "注册赠送积分", null);
    }
}
